import logging
from flask import current_app
from .models import db
import datetime
import random
import string
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
from flask import session, jsonify
import time

def log_security_event(event_type, user=None, ip=None):
    logger = logging.getLogger('security')
    message = f"{event_type} | User: {user.username if user else 'Anonymous'} | IP: {ip}"
    logger.warning(message)

def handle_failed_login(user, ip):
    user.login_attempts += 1
    if user.login_attempts >= current_app.config['MAX_LOGIN_ATTEMPTS']:
        lockout_time = datetime.datetime.utcnow() + datetime.timedelta(
            seconds=current_app.config['LOCKOUT_TIME']
        )
        user.locked_until = lockout_time
        log_security_event('ACCOUNT_LOCKED', user, ip)
    db.session.commit()

def reset_login_attempts(user):
    user.login_attempts = 0
    user.locked_until = None
    db.session.commit()

def sanitize_input(input_str):
    """防止XSS攻击"""
    return input_str.replace('<', '&lt;').replace('>', '&gt;')

# 辅助函数
def generate_captcha_text(length=4):
    """生成随机验证码文本"""
    characters = string.ascii_letters + string.digits
    return ''.join(random.choice(characters) for _ in range(length))


def generte_img(captcha_text):
    # 创建图像
    width, height = 120, 40
    img = Image.new('RGB', (width, height), color=(255, 255, 255))
    draw = ImageDraw.Draw(img)
    
    # 使用系统字体或备用字体
    try:
        font = ImageFont.truetype("arial.ttf", 24)
    except IOError:
        try:
            font = ImageFont.truetype("DejaVuSans.ttf", 24)
        except:
            # 如果找不到字体，使用默认字体
            font = ImageFont.load_default()
    
    # 绘制验证码文本（添加一些干扰）
    for i, char in enumerate(captcha_text):
        x = 10 + i * 25 + random.randint(-5, 5)
        y = 5 + random.randint(-5, 5)
        draw.text((x, y), char, fill=(random.randint(0, 150), random.randint(0, 150), random.randint(0, 150)), font=font)
    
    # 添加干扰线
    for _ in range(5):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)
        draw.line([(x1, y1), (x2, y2)], fill=(random.randint(0, 200), random.randint(0, 200), random.randint(0, 200)), width=1)
    
    # 添加噪点
    for _ in range(100):
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.point((x, y), fill=(random.randint(0, 200), random.randint(0, 200), random.randint(0, 200)))
    
    # 保存图像到字节流
    img_io = BytesIO()
    img.save(img_io, 'PNG')
    img_io.seek(0)

    return img_io


def generate_reset_token(user):
    """生成密码重置令牌（实际实现应使用JWT或类似技术）"""
    import hashlib
    import time
    secret = current_app.config['SECRET_KEY']
    timestamp = str(int(time.time()))
    data = f"{user.id}-{user.email}-{timestamp}"
    return hashlib.sha256(f"{data}{secret}".encode()).hexdigest()

def generate_email_captcha(user):
    """生成验证码"""
    text = generate_reset_token(user)
    captcha_text = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
    session['captcha'] = {
        'text': captcha_text,
        'expire_time': time.time() + current_app.config['CAPTCHA_EXPIRE_TIME']
    }
    return captcha_text

def validate_captcha(captcha_input,stored_captcha):
    # 检查验证码是否有效
    current_time = time.time()
    if not stored_captcha.get('text'):
        session.pop('captcha', None)  # 清除无效验证码
        return jsonify(error="验证码不存在，请刷新重试！"), 400
    if stored_captcha.get('expire_time', 0) < current_time:
        session.pop('captcha', None)  # 清除无效验证码
        return jsonify(error="验证码过期，请刷新重试！"), 400
    if stored_captcha['text'].lower() != captcha_input:
        session.pop('captcha', None)  # 清除无效验证码
        return jsonify(error="验证码错误，请刷新重试！"), 400
    
def format_form_errors(errors):
    """
    将 form.errors 转换为 字符串 形式
    """
    result = []
    for field in errors.values():
        if isinstance(field, list):
            result.extend(field)
        else:
            result.append(field)
    return ';'.join(result)